home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / dev / gg / ncurses-5.3.lha / ncurses-5.3 / test / hanoi.c < prev    next >
C/C++ Source or Header  |  2002-10-24  |  7KB  |  304 lines

  1. /*
  2.  *    Name: Towers of Hanoi.
  3.  *
  4.  *    Desc:
  5.  *        This is a playable copy of towers of hanoi.
  6.  *        Its sole purpose is to demonstrate my Amiga Curses package.
  7.  *        This program should compile on any system that has Curses.
  8.  *        'hanoi'        will give a manual game with 7 playing pieces.
  9.  *        'hanoi n'    will give a manual game with n playing pieces.
  10.  *        'hanoi n a' will give an auto solved game with n playing pieces.
  11.  *
  12.  *    Author: Simon J Raybould    (sie@fulcrum.bt.co.uk).
  13.  *     (This version has been slightly modified by the ncurses maintainers.)
  14.  *
  15.  *    Date: 05.Nov.90
  16.  *
  17.  * $Id: hanoi.c,v 1.24 2002/06/29 23:32:18 tom Exp $
  18.  */
  19.  
  20. #include <test.priv.h>
  21.  
  22. #define NPEGS            3    /* This is not configurable !! */
  23. #define MINTILES        3
  24. #define MAXTILES        9
  25. #define DEFAULTTILES        7
  26. #define TOPLINE            6
  27. #define BASELINE        16
  28. #define STATUSLINE        (LINES-3)
  29. #define LEFTPEG            19
  30. #define MIDPEG            39
  31. #define RIGHTPEG        59
  32.  
  33. #define LENTOIND(x)        (((x)-1)/2)
  34. #define OTHER(a,b)        (3-((a)+(b)))
  35.  
  36. struct Peg {
  37.     size_t Length[MAXTILES];
  38.     int Count;
  39. };
  40.  
  41. static struct Peg Pegs[NPEGS];
  42. static int PegPos[] =
  43. {LEFTPEG, MIDPEG, RIGHTPEG};
  44. static int TileColour[] =
  45. {
  46.     COLOR_GREEN,        /* Length 3 */
  47.     COLOR_MAGENTA,        /* Length 5 */
  48.     COLOR_RED,            /* Length 7 */
  49.     COLOR_BLUE,            /* Length 9 */
  50.     COLOR_CYAN,            /* Length 11 */
  51.     COLOR_YELLOW,        /* Length 13 */
  52.     COLOR_GREEN,        /* Length 15 */
  53.     COLOR_MAGENTA,        /* Length 17 */
  54.     COLOR_RED,            /* Length 19 */
  55. };
  56. static int NMoves = 0;
  57.  
  58. static void InitTiles(int NTiles);
  59. static void DisplayTiles(void);
  60. static void MakeMove(int From, int To);
  61. static void AutoMove(int From, int To, int Num);
  62. static void Usage(void);
  63. static int Solved(int NumTiles);
  64. static int GetMove(int *From, int *To);
  65. static int InvalidMove(int From, int To);
  66.  
  67. int
  68. main(int argc, char **argv)
  69. {
  70.     int NTiles, FromCol, ToCol;
  71.     bool AutoFlag = 0;
  72.  
  73.     setlocale(LC_ALL, "");
  74.  
  75.     switch (argc) {
  76.     case 1:
  77.     NTiles = DEFAULTTILES;
  78.     break;
  79.     case 2:
  80.     NTiles = atoi(argv[1]);
  81.     if (NTiles > MAXTILES || NTiles < MINTILES) {
  82.         fprintf(stderr, "Range %d to %d\n", MINTILES, MAXTILES);
  83.         ExitProgram(EXIT_FAILURE);
  84.     }
  85.     break;
  86.     case 3:
  87.     if (strcmp(argv[2], "a")) {
  88.         Usage();
  89.         ExitProgram(EXIT_FAILURE);
  90.     }
  91.     NTiles = atoi(argv[1]);
  92.     if (NTiles > MAXTILES || NTiles < MINTILES) {
  93.         fprintf(stderr, "Range %d to %d\n", MINTILES, MAXTILES);
  94.         ExitProgram(EXIT_FAILURE);
  95.     }
  96.     AutoFlag = TRUE;
  97.     break;
  98.     default:
  99.     Usage();
  100.     ExitProgram(EXIT_FAILURE);
  101.     }
  102. #ifdef TRACE
  103.     trace(TRACE_MAXIMUM);
  104. #endif
  105.     initscr();
  106.     if (has_colors()) {
  107.     int i;
  108.     int bg = COLOR_BLACK;
  109.     start_color();
  110. #if HAVE_USE_DEFAULT_COLORS
  111.     if (use_default_colors() == OK)
  112.         bg = -1;
  113. #endif
  114.     for (i = 0; i < 9; i++)
  115.         init_pair(i + 1, bg, TileColour[i]);
  116.     }
  117.     cbreak();
  118.     if (LINES < 24) {
  119.     endwin();
  120.     fprintf(stderr, "Min screen length 24 lines\n");
  121.     ExitProgram(EXIT_FAILURE);
  122.     }
  123.     if (AutoFlag) {
  124.     curs_set(0);
  125.     leaveok(stdscr, TRUE);    /* Attempt to remove cursor */
  126.     }
  127.     InitTiles(NTiles);
  128.     DisplayTiles();
  129.     if (AutoFlag) {
  130.     do {
  131.         noecho();
  132.         AutoMove(0, 2, NTiles);
  133.     } while (!Solved(NTiles));
  134.     sleep(2);
  135.     } else {
  136.     echo();
  137.     for (;;) {
  138.         if (GetMove(&FromCol, &ToCol))
  139.         break;
  140.         if (InvalidMove(FromCol, ToCol)) {
  141.         mvaddstr(STATUSLINE, 0, "Invalid Move !!");
  142.         refresh();
  143.         beep();
  144.         continue;
  145.         }
  146.         MakeMove(FromCol, ToCol);
  147.         if (Solved(NTiles)) {
  148.         mvprintw(STATUSLINE, 0,
  149.              "Well Done !! You did it in %d moves", NMoves);
  150.         refresh();
  151.         sleep(5);
  152.         break;
  153.         }
  154.     }
  155.     }
  156.     endwin();
  157.     ExitProgram(EXIT_SUCCESS);
  158. }
  159.  
  160. static int
  161. InvalidMove(int From, int To)
  162. {
  163.     if (From >= NPEGS)
  164.     return TRUE;
  165.     if (From < 0)
  166.     return TRUE;
  167.     if (To >= NPEGS)
  168.     return TRUE;
  169.     if (To < 0)
  170.     return TRUE;
  171.     if (From == To)
  172.     return TRUE;
  173.     if (!Pegs[From].Count)
  174.     return TRUE;
  175.     if (Pegs[To].Count &&
  176.     Pegs[From].Length[Pegs[From].Count - 1] >
  177.     Pegs[To].Length[Pegs[To].Count - 1])
  178.     return TRUE;
  179.     return FALSE;
  180. }
  181.  
  182. static void
  183. InitTiles(int NTiles)
  184. {
  185.     int Size, SlotNo;
  186.  
  187.     for (Size = NTiles * 2 + 1, SlotNo = 0; Size >= 3; Size -= 2)
  188.     Pegs[0].Length[SlotNo++] = Size;
  189.  
  190.     Pegs[0].Count = NTiles;
  191.     Pegs[1].Count = 0;
  192.     Pegs[2].Count = 0;
  193. }
  194.  
  195. static void
  196. DisplayTiles(void)
  197. {
  198.     int Line, peg, SlotNo;
  199.     char TileBuf[BUFSIZ];
  200.  
  201.     erase();
  202.     mvaddstr(1, 24, "T O W E R S   O F   H A N O I");
  203.     mvaddstr(3, 34, "SJR 1990");
  204.     mvprintw(19, 5, "Moves : %d", NMoves);
  205.     attrset(A_REVERSE);
  206.     mvaddstr(BASELINE, 8,
  207.          "                                                               ");
  208.  
  209.     for (Line = TOPLINE; Line < BASELINE; Line++) {
  210.     mvaddch(Line, LEFTPEG, ' ');
  211.     mvaddch(Line, MIDPEG, ' ');
  212.     mvaddch(Line, RIGHTPEG, ' ');
  213.     }
  214.     mvaddch(BASELINE, LEFTPEG, '1');
  215.     mvaddch(BASELINE, MIDPEG, '2');
  216.     mvaddch(BASELINE, RIGHTPEG, '3');
  217.     attrset(A_NORMAL);
  218.  
  219.     /* Draw tiles */
  220.     for (peg = 0; peg < NPEGS; peg++) {
  221.     for (SlotNo = 0; SlotNo < Pegs[peg].Count; SlotNo++) {
  222.         memset(TileBuf, ' ', Pegs[peg].Length[SlotNo]);
  223.         TileBuf[Pegs[peg].Length[SlotNo]] = '\0';
  224.         if (has_colors())
  225.         attrset(COLOR_PAIR(LENTOIND(Pegs[peg].Length[SlotNo])));
  226.         else
  227.         attrset(A_REVERSE);
  228.         mvaddstr(BASELINE - (SlotNo + 1),
  229.              (int) (PegPos[peg] - Pegs[peg].Length[SlotNo] / 2),
  230.              TileBuf);
  231.     }
  232.     }
  233.     attrset(A_NORMAL);
  234.     refresh();
  235. }
  236.  
  237. static int
  238. GetMove(int *From, int *To)
  239. {
  240.     mvaddstr(STATUSLINE, 0, "Next move ('q' to quit) from ");
  241.     clrtoeol();
  242.     refresh();
  243.     if ((*From = getch()) == 'q')
  244.     return TRUE;
  245.     *From -= ('0' + 1);
  246.     addstr(" to ");
  247.     clrtoeol();
  248.     refresh();
  249.  
  250.     if ((*To = getch()) == 'q')
  251.     return TRUE;
  252.     *To -= ('0' + 1);
  253.     refresh();
  254.     napms(500);
  255.  
  256.     move(STATUSLINE, 0);
  257.     clrtoeol();
  258.     refresh();
  259.     return FALSE;
  260. }
  261.  
  262. static void
  263. MakeMove(int From, int To)
  264. {
  265.     Pegs[From].Count--;
  266.     Pegs[To].Length[Pegs[To].Count] = Pegs[From].Length[Pegs[From].Count];
  267.     Pegs[To].Count++;
  268.     NMoves++;
  269.     DisplayTiles();
  270. }
  271.  
  272. static void
  273. AutoMove(int From, int To, int Num)
  274. {
  275.     if (Num == 1) {
  276.     MakeMove(From, To);
  277.     napms(500);
  278.     return;
  279.     }
  280.     AutoMove(From, OTHER(From, To), Num - 1);
  281.     MakeMove(From, To);
  282.     napms(500);
  283.     AutoMove(OTHER(From, To), To, Num - 1);
  284. }
  285.  
  286. static int
  287. Solved(int NumTiles)
  288. {
  289.     int i;
  290.  
  291.     for (i = 1; i < NPEGS; i++)
  292.     if (Pegs[i].Count == NumTiles)
  293.         return TRUE;
  294.     return FALSE;
  295. }
  296.  
  297. static void
  298. Usage(void)
  299. {
  300.     fprintf(stderr, "Usage: hanoi [<No Of Tiles>] [a]\n");
  301.     fprintf(stderr,
  302.         "The 'a' option causes the tower to be solved automatically\n");
  303. }
  304.